/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package negocio;

import exception.MovimentoInvalidoException;
import exception.MovimentoPendenteException;
import java.util.EnumMap;

/**
 *
 * @author jessica.rodrigues
 */
public class Tabuleiro {

	private IPeca[][] pecas = new IPeca[8][8];
	private EnumMap<ECor, Integer> pecasRemovidas = new EnumMap<ECor, Integer>(ECor.class);
	private boolean trocarJogador;
	private boolean acabou = false;

	public Tabuleiro() {
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if ((i % 2 == 0 && j % 2 != 0) || (j % 2 == 0 && i % 2 != 0)) {
					if (i <= 2) {
						pecas[i][j] = new PecaSimples(ECor.PRETO);
					}

					if (i >= 5) {
						pecas[i][j] = new PecaSimples(ECor.BRANCO);
					}
				}
			}
		}
		pecasRemovidas.put(ECor.PRETO, 0);
		pecasRemovidas.put(ECor.BRANCO, 0);
	}

	public IPeca[][] getPecas() {
		return pecas;
	}

	public Integer getPecasRemovidas(ECor cor) {
		return pecasRemovidas.get(cor);
	}

	public void mover(Posicao atual, Posicao proxima, ECor corJogadorAtual) throws MovimentoInvalidoException, MovimentoPendenteException {
		this.setTrocarJogador(true);
		IPeca pecaAtual = this.pecas[atual.getPosicaoY()][atual.getPosicaoX()];

		if (pecaAtual == null
				|| !pecaAtual.getCor().equals(corJogadorAtual)) {
			throw new MovimentoInvalidoException("Não há uma peça do jogador na casa origem.");
		}

		if (this.pecas[proxima.getPosicaoY()][proxima.getPosicaoX()] != null) {
			throw new MovimentoInvalidoException("Já há uma peça na casa destino.");
		}

		if (pecaAtual instanceof PecaSimples) {
			if (!((corJogadorAtual.equals(ECor.PRETO) && proxima.getPosicaoY() - atual.getPosicaoY() > 0) || (corJogadorAtual.equals(ECor.BRANCO) && proxima.getPosicaoY() - atual.getPosicaoY() < 0))) {
				throw new MovimentoInvalidoException("Você só pode andar para frente.");
			}
			int operacaoY = (corJogadorAtual.equals(ECor.PRETO) ? 1 : -1);
			if (atual.getPosicaoY() + 2 < 8
					&& ((atual.getPosicaoX() - 2 >= 0 && this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() - 1] != null
					&& !this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() - 1].getCor().equals(corJogadorAtual))
					|| (atual.getPosicaoX() + 2 < 8 && this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() + 1] != null
					&& !this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() + 1].getCor().equals(corJogadorAtual)))) {

				if (!(Math.abs(proxima.getPosicaoX() - atual.getPosicaoX()) == 2 && proxima.getPosicaoY() - atual.getPosicaoY() == 2 * operacaoY)) {
					throw new MovimentoPendenteException("Há peças a comer.");
				} else {
					this.pecas[atual.getPosicaoY()][atual.getPosicaoX()] = null;
					this.pecas[atual.getPosicaoY() + operacaoY][(proxima.getPosicaoX() - atual.getPosicaoX() > 0 ? atual.getPosicaoX() + 1 : atual.getPosicaoX() - 1)] = null;
					if (corJogadorAtual.equals(ECor.BRANCO)) {
						pecasRemovidas.put(ECor.PRETO, pecasRemovidas.get(ECor.PRETO) + 1);
					} else {
						pecasRemovidas.put(ECor.BRANCO, pecasRemovidas.get(ECor.BRANCO) + 1);
					}

					if (atual.getPosicaoY() + 1 < 8
							&& ((atual.getPosicaoX() - 1 >= 0 && this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() - 1] != null
							&& !this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() - 1].getCor().equals(corJogadorAtual))
							|| (atual.getPosicaoX() + 1 < 8 && this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() + 1] != null
							&& !this.pecas[atual.getPosicaoY() + operacaoY][atual.getPosicaoX() + 1].getCor().equals(corJogadorAtual)))) {
						this.setTrocarJogador(false);
					}
				}
			} else {
				if (Math.abs(proxima.getPosicaoY() - atual.getPosicaoY()) != 1 || Math.abs(proxima.getPosicaoX() - atual.getPosicaoX()) != 1) {
					throw new MovimentoInvalidoException("Você só pode andar uma casa na diagonal.");
				} else {
					this.pecas[atual.getPosicaoY()][atual.getPosicaoX()] = null;
				}
			}
			if((pecaAtual.getCor().equals(ECor.PRETO) && proxima.getPosicaoY() == 7) || (pecaAtual.getCor().equals(ECor.BRANCO) && proxima.getPosicaoY() == 0)) {
				this.pecas[proxima.getPosicaoY()][proxima.getPosicaoX()] = new Dama(corJogadorAtual);
			}else {
				this.pecas[proxima.getPosicaoY()][proxima.getPosicaoX()] = pecaAtual;
			}
		} else if (pecaAtual instanceof Dama) {
			Dama peca = (Dama) pecaAtual;

			//Verfica se a posicao de destino esta na diagonal da dama.
			if (Math.abs(atual.getPosicaoX() - proxima.getPosicaoX()) != Math.abs(atual.getPosicaoY() - proxima.getPosicaoY())) {
				throw new MovimentoPendenteException("Movimento de dama inválido.");
			} else {
				peca.validImpedimento(this, atual, proxima);
			}
			peca.removeInimigo(this, atual, proxima);
			this.pecas[atual.getPosicaoY()][atual.getPosicaoX()] = null;
			this.pecas[proxima.getPosicaoY()][proxima.getPosicaoX()] = peca;
		}

		if (pecasRemovidas.get(ECor.BRANCO) == 12 || pecasRemovidas.get(ECor.PRETO) == 12) {
			this.acabou = true;
		}
	}

	public boolean getTrocarJogador() {
		return this.trocarJogador;
	}

	public void setTrocarJogador(boolean trocar) {
		this.trocarJogador = trocar;
	}

	@Override
	public String toString() {
		StringBuffer tabuleiro = new StringBuffer();
		tabuleiro.append("  01234567\n");
		for (int i = 0; i < 8; i++) {
			tabuleiro.append(i).append(" ");
			for (int j = 0; j < 8; j++) {
				if (this.getPecas()[i][j] == null) {
					tabuleiro.append("-");
				} else {
					if (this.getPecas()[i][j].getCor().equals(ECor.PRETO)) {
						tabuleiro.append("P");
					}
					if (this.getPecas()[i][j].getCor().equals(ECor.BRANCO)) {
						tabuleiro.append("B");
					}
				}
			}
			tabuleiro.append("\n");
		}
		return tabuleiro.toString();
	}

	public boolean acabou() {
		return this.acabou;
	}

	public IPeca getPeca(int x, int y) {
		return this.pecas[x][y];
	}

	public void setPeca(IPeca peca, int x, int y) {
		this.pecas[x][y] = peca;
	}
}